<?php

namespace Cheny\Route;

/**
 * 路由类
 * @method static Route get(string $route, Callable $callback)
 * @method static Route post(string $route, Callable $callback)
 */
class Route
{

    /**
     * @var array 路由映射表
     */
    private static $routes = [];

    /**
     * @var string|object 错误指向路由或处理方法
     */
    private static $error_callback = false;

    public static function __callstatic($method, $params)
    {
        $method = strtoupper($method);
        $uri = strtolower($params[0]);
        $callback = $params[1];

        static::$routes[$method][$uri] = $callback;
    }
    
    /**
     * 批量注册路由
     * @param array $routes 需要注册的路由数组，格式为：
     * [
     *     // ['method', 'uri', 'handle function']
     *     ['get', 'hello', 'App\Controller\Hello@index']
     * ]
     * @return void
     */
    public static function register($routes)
    {
        foreach ($routes as $route)
        {
            static::{$route[0]}($route[1], $route[2]);
        }
    }

    /**
     * 注册错误路由或错误处理方法
     * @param string|object $callback 路由字符串或闭包
     * @return void
     */
    public static function error($callback)
    {
        static::$error_callback = $callback;
    }

    /**
     * 处理路由
     * @return void
     */
    public static function dispatch()
    {
        $uri = trim(strtolower(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)), '/');
        $method = strtoupper($_SERVER['REQUEST_METHOD']);

        // 路由规则匹配
        if (isset(static::$routes[$method][$uri]))
        {
            $callback = static::$routes[$method][$uri];
            if (is_object($callback))
            {
                // 闭包
                call_user_func($callback);
            }
            else
            {
                //  调用 Controller
                $handle = explode('@', $callback);
                $controller_name = $handle[0];
                $method_name = $handle[1];

                $controller = new $controller_name();
                $controller->$method_name();
            }
            return;
        }

        // 错误处理
        if (!static::$error_callback)
        {
            throw new \UnexpectedValueException('404 Not Found');
        }
        elseif (is_string(static::$error_callback))
        {
            static::get($uri, static::$error_callback);
            static::$error_callback = false;
            static::dispatch();
        }
        elseif (static::$error_callback !== null)
        {
            call_user_func(static::$error_callback);
        }
    }
}